package com.bzg.baseSpringComponent.beanDefinition;

import com.bzg.spring.component.UserService;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

/**
 * beanDefinition，spring的核心组件之一。每个创建的bean首先都要被创建为一个beanDefinition,来存储这个bean的相关信息
 * 然后基于beanDefinition来构建bean。BeanDefinition有很多种。但都是在AbstractBeanDefinition之上进行了一点扩展
 * 所以区别不大。
 * 1、AnnotatedGenericBeanDefinition，带有注解的beanDefinition
 * 2、ScannedGenericBeanDefinition，基于包名扫描得到的beanDefinition
 * 3、GenericBeanDefinition，一个通用的beanDefinition，基本只是纯粹实现了AbstractBeanDefinition。也是上面两个的父类
 * 4、RootBeanDefinition,这是一个比较强大的BeanDefinition，很多bean的上层信息都会记录在里面。该bean往往不会直接创建
 * 而是由spring在执行过程中将其他类型beanDefinition转为RootBeanDefinition。如：beanDefinition的合并
 * BeanDefinition基本常用的就上面4种
 * */
public class BeanDefinitionStyle {

	public static void main(String[] args) {
		/**
		 * beanDefinition的构建方式
		 * */
		// 1、由BeanDefinitionBuilder可以构建一个rootBeanDefinition或GenericBeanDefinition
//		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(UserService.class).getBeanDefinition();

		/**
		 * 由各种BeanDefinitionReader去读取并注册BeanDefinition(注意：前提是这些组件要带有@Component注解)
		 * */
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		//2、AnnotatedBeanDefinitionReader可以基于Class去去构建一个AnnotatedGenericBeanDefinition，并注册到容器context中
		// 这种BeanDefinition是基于Class的，会封装class上的注解信息
		AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
		annotatedBeanDefinitionReader.register(UserService.class);

		//3、基于xml文件创建BeanDefinition，并注册到容器，这种reader会解析xml中的<bean>标签，将其封装为GenericBeanDefinition
		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
		xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

		//4、基于包名扫描，将组件(含有@component)封装为ScannedGenericBeanDefinition，并注入容器
		ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(context);
		classPathBeanDefinitionScanner.scan("com.bzg");
		// 以上4中方式都可以构建BeanDefinition（当然，也可以直接直接new）。context自己也是可以直接注册的，因为它内部也含有部分Reader
	}
}
